package com.rajaev.dtu.tractor.infrastructure.advice;


import com.rajaev.dtu.tractor.infrastructure.base.errors.BusinessException;
import com.rajaev.dtu.tractor.infrastructure.base.errors.ErrorCodes;
import com.rajaev.dtu.tractor.infrastructure.base.resp.ResponseInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.validation.constraints.NotNull;

@ControllerAdvice(basePackages = "com.rajaev.dtu.tractor.interfaces")
@Slf4j
public class MyControllerAdvice implements ResponseBodyAdvice {


    @ResponseBody
    @ExceptionHandler(value = BusinessException.class)
    public ResponseInfo<Void> errorHandler(@NotNull BusinessException ex) {
        log.info("<<<<<<<<<<BusinessException:{},{},{}<<<<<<<<<<<<<<", ex.getErrorCode(), ex.getInnerErrorMsg(), ex.getOutErrorMsg());
        ResponseInfo<Void> responseInfo = new ResponseInfo<>();
        responseInfo.setRespCode(ex.getErrorCode());
        responseInfo.setErrorMsg(ex.getOutErrorMsg());
        return responseInfo;
    }

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ResponseInfo<Void> errorHandler(@NotNull Exception ex) {
        log.error("<<<<<<<<<<SystemException<<<<<<<<<<<<<<", ex);
        ResponseInfo<Void> responseInfo = new ResponseInfo<>();
        responseInfo.setRespCode(ErrorCodes.ERR_SYSTEM.getErrorCode());
        responseInfo.setErrorMsg(ErrorCodes.ERR_SYSTEM.getOutErrorMsg());
        return responseInfo;
    }


    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }


    @Override
    @ResponseBody
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        methodParameter.getMethod().getDeclaringClass();
        if (body instanceof ResponseInfo) {
            return body;
        } else if (body instanceof String) {
            // 如果在controller层中返回的是String类型，这边如果换成ResponseEntity的话，会导致StringMessageConverter方法类型转换异常，所以这边将对象转成字符串
            String msg = (String) body;
            ResponseInfo responseInfo = new ResponseInfo();
            responseInfo.setData(msg);
            return responseInfo;

        } else if (body instanceof Byte[]) {
            return body;
        } else {
            ResponseInfo responseInfo = new ResponseInfo();
            responseInfo.setData(body);
            return responseInfo;
        }
    }
}
